using System;
using ch.ethz.ssh2.util;
using Org.BouncyCastle.Math;
namespace ch.ethz.ssh2.packets
{

    /// <summary> TypesWriter.
    /// 
    /// </summary>
    /// <author>  Christian Plattner
    /// </author>
    /// <version>  2.50, 03/15/10
    /// </version>
    public class TypesWriter
    {
        internal byte[] arr;
        internal int pos;

        public TypesWriter()
        {
            arr = new byte[256];
            pos = 0;
        }

        private void resize(int len)
        {
            byte[] new_arr = new byte[len];
            Array.Copy(arr, 0, new_arr, 0, arr.Length);
            arr = new_arr;
        }

        public virtual int length()
        {
            return pos;
        }

        public virtual byte[] getBytes()
        {
            byte[] dst = new byte[pos];
            Array.Copy(arr, 0, dst, 0, pos);
            return dst;
        }

        public virtual void getBytes(byte[] dst)
        {
            Array.Copy(arr, 0, dst, 0, pos);
        }

        public virtual void writeUINT32(int val, int off)
        {
            if ((off + 4) > arr.Length)
                resize(off + 32);

            arr[off++] = (byte)(val >> 24);
            arr[off++] = (byte)(val >> 16);
            arr[off++] = (byte)(val >> 8);
            arr[off++] = (byte)val;
        }

        public virtual void writeUINT32(int val)
        {
            writeUINT32(val, pos);
            pos += 4;
        }

        public virtual void writeUINT64(long val)
        {
            if ((pos + 8) > arr.Length)
                resize(arr.Length + 32);

            arr[pos++] = (byte)(val >> 56);
            arr[pos++] = (byte)(val >> 48);
            arr[pos++] = (byte)(val >> 40);
            arr[pos++] = (byte)(val >> 32);
            arr[pos++] = (byte)(val >> 24);
            arr[pos++] = (byte)(val >> 16);
            arr[pos++] = (byte)(val >> 8);
            arr[pos++] = (byte)val;
        }

        public virtual void writeBoolean(bool v)
        {
            if ((pos + 1) > arr.Length)
                resize(arr.Length + 32);

            arr[pos++] = v ? (byte)1 : (byte)0;
        }

        public virtual void writeByte(int v, int off)
        {
            if ((off + 1) > arr.Length)
                resize(off + 32);

            arr[off] = (byte)v;
        }

        public virtual void writeByte(int v)
        {
            writeByte(v, pos);
            pos++;
        }

        public virtual void writeMPInt(BigInteger b)
        {
            byte[] raw = b.ToByteArray();

            if ((raw.Length == 1) && (raw[0] == 0))
                writeUINT32(0);
            /* String with zero bytes of data */
            else
                writeString(raw, 0, raw.Length);
        }

        public virtual void writeBytes(byte[] buff)
        {
            writeBytes(buff, 0, buff.Length);
        }

        public virtual void writeBytes(byte[] buff, int off, int len)
        {
            if ((pos + len) > arr.Length)
                resize(arr.Length + len + 32);

            Array.Copy(buff, off, arr, pos, len);
            pos += len;
        }

        public virtual void writeString(byte[] buff, int off, int len)
        {
            writeUINT32(len);
            writeBytes(buff, off, len);
        }

        public virtual void writeString(System.String v)
        {
            byte[] b = StringEncoder.GetBytes(v);

            writeUINT32(b.Length);
            writeBytes(b, 0, b.Length);
        }

        public virtual void writeString(System.String v, System.String charsetName)
        {
            byte[] b = (charsetName == null) ? StringEncoder.GetBytes(v) : System.Text.Encoding.GetEncoding(charsetName).GetBytes(v);

            writeUINT32(b.Length);
            writeBytes(b, 0, b.Length);
        }

        public virtual void writeNameList(System.String[] v)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (int i = 0; i < v.Length; i++)
            {
                if (i > 0)
                    sb.Append(',');
                sb.Append(v[i]);
            }
            writeString(sb.ToString());
        }
    }
}